class LinkedList {
  constructor() {
    this.head = null;
    this.length = 0;
  }

  append(data) {
    let el = new LinkedList.LinkedListElement(data);
    if (this.length === 0) {
      this.head = el;
    } else {
      let current = this.head;
      while (current.next) {
        current = current.next;
      }
      current.next = el;
    }
    this.length++;
    return this;
  }

  insert(position, data) {
    //索引越界排除
    if (position < 0 || position > this.length) return false;
    const newNode = new LinkedList.LinkedListElement(data);
    // let previous = this.head
    if (position === 0) {
      newNode.next = this.head;
      this.head = newNode;
    } else {
      let previous = this.head;
      let current = this.head.next;
      let idx = 0;
      while (++idx < position) {
        previous = previous.next;
        current = current.next;
      }
      newNode.next = current;
      previous.next = newNode;
    }
    this.length++;
    return this;
  }

  get(position) {
    //越界判断
    if (position < 0 || position >= this.length) return null;
    let current = this.head;
    let idx = 0;
    while (idx++ < position) {
      current = current.next;
    }
    return current.data;
  }

  indexOf(el) {
    let idx = 0;
    let current = this.head;
    while (idx < this.length) {
      if (current.data === el) return idx;
      idx++;
      current = current.next;
    }
    return -1;
  }

  update(position, data) {
    if (position < 0 || position >= this.length) return false;
    let current = this.head;
    let idx = 0;
    while (idx++ < position) {
      current = current.next;
    }
    current.data = data;
    return true;
  }

  removeAt(position) {
    if (position < 0 || position >= this.length) return null;
    let current = this.head;
    let previous = this.head;
    if (position === 0) {
      this.head = this.head.next;
    } else {
      let idx = 0;
      current = this.head.next;
      while (++idx < position) {
        current = current.next;
        previous = previous.next;
      }
      previous.next = current.next;
    }
    this.length--;
    return current.data;
  }

  remove(el) {
    let idx = this.indexOf(el);
    if (idx === -1) {
      return false;
    }
    return removeAt(idx);
  }

  isEmpty() {
    return this.length === 0;
  }

  size() {
    return this.length;
  }

  toString() {
    let ret = "";
    let node = this.head;
    for (let i = 0; i < this.length; i++) {
      ret += node.data + " ";
      node = node.next;
    }
    return ret;
  }
}

LinkedList.LinkedListElement = class {
  constructor(data) {
    this.data = data;
    this.next = null;
  }
};

let a = new LinkedList();
console.log(a.append(11).append(22).append(3333).toString());
// console.log(a.insert(2, 00).toString());
// console.log(a.get(3));
// console.log(a.update(1, 1));
console.log(a.removeAt(2));
console.log(a.toString());
